﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Xml.Serialization;
using System.IO;

namespace BigPang.Render
{
    [Serializable]
    public class Map : Renderable
    {
        [NonSerialized]
        Bitmap[] mBitmaps;

        [NonSerialized]
        Bitmap mFreeBitmap;

        [NonSerialized]
        Image[] mBuffers;

        [NonSerialized]
        Image mFreeBuffer;

        [NonSerialized]
        Graphics[] mGraphs;

        [NonSerialized]
        Graphics mFreeGraph;

        public static Map TheMap { get; private set; }

        public const int TileSize = 32;

        [Serializable]
        public struct TileData
        {
            public int bitmapId;
        }

        public bool[] FreeMap;

        public TileData[] TileDatas;

        public int Width { get; set; }
        public int Height { get; set; }

        public string[] ImageFileNames;

        [NonSerialized]
        public bool IsShowFreeMap;


        public Map()
        {

        }

        public Map(string[] imageFileName, int width, int height)
        {
            ImageFileNames = imageFileName;

            Width = width;
            Height = height;
            int page = width * height;

            TileDatas = new TileData[ImageFileNames.Length * Width * Height];
            FreeMap = new bool[ImageFileNames.Length * Width * Height];

            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    for (int k = 1; k < imageFileName.Length; k++)
                        TileDatas[k * page + j * width + i].bitmapId = -1;

                    FreeMap[j * width + i] = true;
                }
            }


        }

        public void Init()
        {
            mBitmaps = new Bitmap[ImageFileNames.Length];
            mBuffers = new Bitmap[ImageFileNames.Length];
            mGraphs = new Graphics[ImageFileNames.Length];

            mFreeBitmap = Bitmap.FromFile("./ResData/MARK_1.png") as Bitmap;

            mFreeBuffer = new Bitmap(Width * TileSize, Height * TileSize);
            mFreeGraph = Graphics.FromImage(mFreeBuffer);

            for (int i = 0; i < ImageFileNames.Length; i++)
            {
                mBitmaps[i] = Bitmap.FromFile(ImageFileNames[i]) as Bitmap;

                mBuffers[i] = new Bitmap(Width * TileSize, Height * TileSize);
                mGraphs[i] = Graphics.FromImage(mBuffers[i]);
            }

            initTiles();

            TheMap = this;
            IsShowFreeMap = true;
        }

        public void SaveFile(string fileName)
        {
            try
            {
                XmlSerializer s = new XmlSerializer(GetType());
                FileStream fs = new FileStream(fileName, FileMode.Create);
                s.Serialize(fs, this);
                fs.Close();
            }
            catch (Exception e)
            {

            }
        }

        public static Map LoadFile(string fileName)
        {
            Map m;

            XmlSerializer s = new XmlSerializer(typeof(Map));
            FileStream fs = new FileStream(fileName, FileMode.Open);
            m = s.Deserialize(fs) as Map;
            m.Init();
            return m;
        }

        void initTiles()
        {
            int page = Width * Height;


            for (int j = 0; j < Width; j++)
            {
                for (int k = 0; k < Height; k++)
                {
                    for (int i = 0; i < ImageFileNames.Length; i++)
                    {
                        int id = TileDatas[page * i + k * Width + j].bitmapId;

                        int xLength = mBitmaps[i].Width / TileSize;
                        int yLength = mBitmaps[i].Height / TileSize;

                        if (id > -1)
                            mGraphs[i].DrawImage(mBitmaps[i], new Rectangle(j * TileSize, k * TileSize, TileSize, TileSize), new Rectangle((id % xLength) * TileSize, (id / xLength) * TileSize, TileSize, TileSize), GraphicsUnit.Pixel);
                    }

                    bool canPass= FreeMap[ k * Width + j ];
                    if (!canPass)
                        mFreeGraph.DrawImage(mFreeBitmap, new Rectangle(j * TileSize, k * TileSize, TileSize, TileSize), new Rectangle(TileSize, 0, TileSize, TileSize), GraphicsUnit.Pixel);
                    else
                        mFreeGraph.FillRectangle(new SolidBrush(Color.Transparent), new Rectangle(j * TileSize, k * TileSize, TileSize, TileSize));
                }
            }
        }

        public override void OnRender(Graphics graph)
        {
            for (int i = 0; i < mBitmaps.Count(); i++)
            {
                graph.DrawImageUnscaled(mBuffers[i], 0, 0);
            }

            if (IsShowFreeMap)
                graph.DrawImageUnscaled(mFreeBuffer, 0, 0);
        }

        public void render(Graphics graph, int layerId)
        {
            try
            {
                graph.DrawImageUnscaled(mBuffers[layerId], 0, 0);
            }
            catch
            {
            }
        }

        public void SetPass(int x, int y, bool canPass)
        {
            FreeMap[y * Width + x] = canPass;

            if( !canPass )
                mFreeGraph.DrawImage(mFreeBitmap, new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), new Rectangle(TileSize, 0, TileSize, TileSize), GraphicsUnit.Pixel);
            else
               mFreeGraph.FillRectangle(new SolidBrush(Color.Transparent), new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize));
        }

        public bool CanPass(int x, int y)
        {
            return FreeMap[y * Width + x];
        }

        public void SetTile(int layerId, int x, int y, int tileIndex)
        {
            try
            {
                TileData td = TileDatas[layerId * Width * Height + y * Width + x];
                td.bitmapId = tileIndex;

                TileDatas[layerId * Width * Height + y * Width + x] = td;

                int xLength = mBitmaps[layerId].Width / TileSize;
                int yLength = mBitmaps[layerId].Height / TileSize;

                mGraphs[layerId].DrawImage(mBitmaps[layerId], new Rectangle(x * TileSize, y * TileSize, TileSize, TileSize), new Rectangle((tileIndex % xLength) * TileSize, (tileIndex / xLength) * TileSize, TileSize, TileSize), GraphicsUnit.Pixel);
            }
            catch { }
        }
    }
}
